using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using JGSY.CMS.LowCode.Platform.Domain.Entities;
using JGSY.CMS.LowCode.Platform.Domain.Interfaces;
using JGSY.CMS.LowCode.Platform.Infrastructure.CmsDbContext;

namespace JGSY.CMS.LowCode.Platform.Infrastructure.Repositories
{
    /// <summary>
    /// 审计日志仓储实现
    /// 提供审计日志实体的数据访问功能实现
    /// </summary>
    public class AuditLogRepository : Repository<AuditLog>, IAuditLogRepository
    {
        public AuditLogRepository(LowCodeDbContext context) : base(context)
        {
        }

        /// <summary>
        /// 获取所有审计日志
        /// </summary>
        /// <returns>审计日志列表</returns>
        public override async Task<List<AuditLog>> GetAllAsync()
        {
            return await _context.AuditLogs
                .OrderByDescending(x => x.Timestamp)
                .ToListAsync();
        }

        // 显式接口：返回 IEnumerable 以契合接口签名
        async Task<IEnumerable<AuditLog>> IAuditLogRepository.GetAllAsync()
            => await GetAllAsync();

        /// <summary>
        /// 根据ID获取审计日志
        /// </summary>
        /// <param name="id">审计日志标识符</param>
        /// <returns>审计日志实体，如果不存在则返回null</returns>
        public async Task<AuditLog?> GetByIdAsync(long id)
        {
            return await _context.AuditLogs
                .FirstOrDefaultAsync(x => x.Id == id);
        }

        /// <summary>
        /// 添加新的审计日志
        /// </summary>
        /// <param name="entity">审计日志实体</param>
        /// <returns>添加操作的异步任务</returns>
        public override async Task<AuditLog> AddAsync(AuditLog entity)
        {
            entity.Timestamp = DateTime.UtcNow;
            await _context.AuditLogs.AddAsync(entity);
            await _context.SaveChangesAsync();
            return entity;
        }

        // 显式接口：接口为 Task 版本
        async Task IAuditLogRepository.AddAsync(AuditLog entity)
        {
            _ = await AddAsync(entity);
        }

        /// <summary>
        /// 查询审计日志
        /// 根据指定条件查询审计日志记录
        /// </summary>
        /// <param name="type">操作类型</param>
        /// <param name="userId">用户标识符</param>
        /// <param name="start">开始时间，可选</param>
        /// <param name="end">结束时间，可选</param>
        /// <param name="resource">资源名称，默认为空字符串</param>
        /// <returns>符合条件的审计日志列表</returns>
        public async Task<IEnumerable<AuditLog>> QueryAsync(string type, long userId, DateTime? start, DateTime? end, string resource = "")
        {
            var query = _context.AuditLogs.AsQueryable();

            if (!string.IsNullOrEmpty(type))
                query = query.Where(x => x.Type != null && x.Type.Contains(type));

            if (userId > 0)
                query = query.Where(x => x.UserId == userId.ToString());

            if (start.HasValue)
                query = query.Where(x => x.Timestamp >= start.Value);

            if (end.HasValue)
                query = query.Where(x => x.Timestamp <= end.Value);

            if (!string.IsNullOrEmpty(resource))
                query = query.Where(x => x.Resource != null && x.Resource.Contains(resource));

            return await query.OrderByDescending(x => x.Timestamp).ToListAsync();
        }

        /// <summary>
        /// 获取按时间分组的统计信息
        /// </summary>
        /// <param name="days">统计天数</param>
        /// <returns>统计结果</returns>
        public async Task<Dictionary<string, int>> GetStatisticsByDaysAsync(int days = 30)
        {
            var startDate = DateTime.UtcNow.Date.AddDays(-days);
            
            var statistics = await _context.AuditLogs
                .Where(x => x.Timestamp >= startDate)
                .GroupBy(x => x.Timestamp.Date)
                .Select(g => new { Date = g.Key, Count = g.Count() })
                .OrderBy(x => x.Date)
                .ToDictionaryAsync(x => x.Date.ToString("yyyy-MM-dd"), x => x.Count);

            return statistics;
        }

        /// <summary>
        /// 获取按操作类型分组的统计信息
        /// </summary>
        /// <returns>统计结果</returns>
        public async Task<Dictionary<string, int>> GetStatisticsByTypeAsync()
        {
            return await _context.AuditLogs
                .GroupBy(x => x.Type)
                .ToDictionaryAsync(g => g.Key, g => g.Count());
        }

        /// <summary>
        /// 获取按用户分组的统计信息
        /// </summary>
        /// <param name="top">返回前N个用户</param>
        /// <returns>统计结果</returns>
        public async Task<Dictionary<string, int>> GetStatisticsByUserAsync(int top = 10)
        {
            return await _context.AuditLogs
                .Where(x => !string.IsNullOrEmpty(x.UserName))
                .GroupBy(x => x.UserName)
                .OrderByDescending(g => g.Count())
                .Take(top)
                .ToDictionaryAsync(g => g.Key, g => g.Count());
        }

        /// <summary>
        /// 清理过期的审计日志
        /// </summary>
        /// <param name="beforeDate">清理此时间之前的日志</param>
        /// <returns>被清理的记录数</returns>
        public async Task<int> CleanupAsync(DateTime beforeDate)
        {
            var logsToDelete = await _context.AuditLogs
                .Where(x => x.Timestamp < beforeDate)
                .ToListAsync();

            _context.AuditLogs.RemoveRange(logsToDelete);
            await _context.SaveChangesAsync();

            return logsToDelete.Count;
        }

        /// <summary>
        /// 批量添加审计日志
        /// </summary>
        /// <param name="entities">审计日志列表</param>
        /// <returns>添加操作的异步任务</returns>
        public async Task BatchAddAsync(IEnumerable<AuditLog> entities)
        {
            var logs = entities.ToList();
            foreach (var log in logs)
            {
                if (log.Timestamp == default)
                    log.Timestamp = DateTime.UtcNow;
            }

            await _context.AuditLogs.AddRangeAsync(logs);
            await _context.SaveChangesAsync();
        }

        /// <summary>
        /// 按分页获取审计日志
        /// </summary>
        /// <param name="pageIndex">页索引，从1开始</param>
        /// <param name="pageSize">页大小</param>
        /// <param name="type">操作类型过滤</param>
        /// <param name="userId">用户ID过滤</param>
        /// <param name="resource">资源过滤</param>
        /// <returns>分页结果</returns>
        public async Task<(List<AuditLog> Items, int TotalCount)> GetPagedAsync(
            int pageIndex = 1, 
            int pageSize = 20, 
            string? type = null, 
            string? userId = null, 
            string? resource = null)
        {
            var query = _context.AuditLogs.AsQueryable();

            if (!string.IsNullOrEmpty(type))
                query = query.Where(x => x.Type != null && x.Type.Contains(type));

            if (!string.IsNullOrEmpty(userId))
                query = query.Where(x => x.UserId == userId);

            if (!string.IsNullOrEmpty(resource))
                query = query.Where(x => x.Resource != null && x.Resource.Contains(resource));

            var totalCount = await query.CountAsync();
            
            var items = await query
                .OrderByDescending(x => x.Timestamp)
                .Skip((pageIndex - 1) * pageSize)
                .Take(pageSize)
                .ToListAsync();

            return (items, totalCount);
        }
    }
}
